package cn.fintecher.pangolin.common.utils;

import cn.fintecher.pangolin.common.annotation.ExcelAnno;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.CaseInfoPropertyResponse;
import cn.fintecher.pangolin.common.model.UploadFile;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.*;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @Author:peishouwen
 * @Desc: 导出数据到Excel
 * @Date:Create in 18:38 2018/8/29
 */
public class ExportDataToExcelUtil {

    /**
     * Excel 文件类型
     */
    public static final String EXCEL_TYPE_XLSX = "xlsx";

    public static final int ROW_MEMORY = 1000;


    /**
     * @param dataList   原始数据
     * @param titleNames 标题项
     * @param dataPros   属性值
     * @param filePath   文件路径+文件名称
     */
    public static void exportToExcel(List<?> dataList, String[] titleNames, String[] dataPros, String filePath) throws BadRequestException {
        if (Objects.isNull(dataList) || dataList.isEmpty()) {
            throw new BadRequestException(null, "exportToExcel", "无相应数据供导出");
        }
        FileOutputStream fos = null;
        SXSSFWorkbook wb = null;
        try {
            fos = new FileOutputStream(filePath);
            wb = new SXSSFWorkbook(ROW_MEMORY);
            CellStyle cellHeadStyle = headCellType(wb);
            CellStyle dataStyle = dataCellType(wb);
            //写入头信息
            Sheet sheet = null;
            sheet = wb.createSheet("sheet");
            Row row = sheet.createRow(0);
            for (int i = 0; i < titleNames.length; i++) {
                Cell cell = row.createCell(i);
                cell.setCellStyle(cellHeadStyle);
                cell.setCellValue(titleNames[i]);
                sheet.setColumnWidth(i, 7000);
            }
            for (int rowIndex = 0; rowIndex < dataList.size(); rowIndex++) {
                Row dataRow = sheet.createRow(rowIndex + 1);
                for (int colIndex = 0; colIndex < dataPros.length; colIndex++) {
                    Cell cell = dataRow.createCell(colIndex);
                    cell.setCellStyle(dataStyle);
                    Field field = dataList.get(rowIndex).getClass().getDeclaredField(dataPros[colIndex]);
                    if (Objects.nonNull(field)) {
                        //设置对象的访问权限，保证对private的属性的访问
                        field.setAccessible(true);
                        if (Objects.equals(field.getType().getName(), "java.util.Date")) {
                            cell.setCellValue(Objects.nonNull(field.get(dataList.get(rowIndex))) ? ZWDateUtil.fomratterDate((Date) field.get(dataList.get(rowIndex)), "yyy-MM-dd") : null);
                        } else {
                            cell.setCellValue(Objects.nonNull(field.get(dataList.get(rowIndex))) ? field.get(dataList.get(rowIndex)).toString() : null);
                        }
                    }
                }
            }
            wb.write(fos);
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequestException(null, "exportToExcel", "导出数据失败");
        } finally {
            try {
                if (Objects.isNull(fos)) {
                    fos.flush();
                    fos.close();
                }
                if (Objects.isNull(wb)) {
                    wb.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //手动清除list
            dataList.clear();
        }
    }

    /**
     * 文件不需要生成表头
     * @param dataList   原始数据
     * @param dataPros   属性值
     * @param filePath   文件路径+文件名称
     */
    public static void exportToExcel(List<?> dataList, String[] dataPros, String filePath) throws BadRequestException {
        if (Objects.isNull(dataList) || dataList.isEmpty()) {
            throw new BadRequestException(null, "exportToExcel", "无相应数据供导出");
        }
        FileOutputStream fos = null;
        SXSSFWorkbook wb = null;
        try {
            fos = new FileOutputStream(filePath);
            wb = new SXSSFWorkbook(ROW_MEMORY);
            CellStyle cellHeadStyle = headCellType(wb);
            CellStyle dataStyle = dataCellType(wb);
            //写入头信息
            Sheet sheet = null;
            sheet = wb.createSheet("sheet");
           /* Row row = sheet.createRow(0);
            for (int i = 0; i < titleNames.length; i++) {
                Cell cell = row.createCell(i);
                cell.setCellStyle(cellHeadStyle);
                cell.setCellValue(titleNames[i]);
                sheet.setColumnWidth(i, 7000);
            }*/
            for (int rowIndex = 0; rowIndex < dataList.size(); rowIndex++) {
                Row dataRow = sheet.createRow(rowIndex + 1);
                for (int colIndex = 0; colIndex < dataPros.length; colIndex++) {
                    Cell cell = dataRow.createCell(colIndex);
                    cell.setCellStyle(dataStyle);
                    Field field = dataList.get(rowIndex).getClass().getDeclaredField(dataPros[colIndex]);
                    if (Objects.nonNull(field)) {
                        //设置对象的访问权限，保证对private的属性的访问
                        field.setAccessible(true);
                        if (Objects.equals(field.getType().getName(), "java.util.Date")) {
                            cell.setCellValue(Objects.nonNull(field.get(dataList.get(rowIndex))) ? ZWDateUtil.fomratterDate((Date) field.get(dataList.get(rowIndex)), "yyy-MM-dd") : null);
                        } else {
                            cell.setCellValue(Objects.nonNull(field.get(dataList.get(rowIndex))) ? field.get(dataList.get(rowIndex)).toString() : null);
                        }
                    }
                }
            }
            wb.write(fos);
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequestException(null, "exportToExcel", "导出数据失败");
        } finally {
            try {
                if (Objects.isNull(fos)) {
                    fos.flush();
                    fos.close();
                }
                if (Objects.isNull(wb)) {
                    wb.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //手动清除list
            dataList.clear();
        }
    }
    public static void exportToExcelForRecord(List<?> dataList, String[] titleNames, String filePath) throws BadRequestException {
        if (Objects.isNull(dataList) || dataList.isEmpty()) {
            throw new BadRequestException(null, "exportToExcel", "无相应数据供导出");
        }
        FileOutputStream fos = null;
        SXSSFWorkbook wb = null;
        try {
            fos = new FileOutputStream(filePath);
            wb = new SXSSFWorkbook(ROW_MEMORY);
            CellStyle cellHeadStyle = headCellType(wb);
            CellStyle dataStyle = dataCellType(wb);
            //写入头信息
            Sheet sheet = null;
            sheet = wb.createSheet("sheet");
            Row row = sheet.createRow(0);
            for (int i = 0; i < titleNames.length; i++) {
                Cell cell = row.createCell(i);
                cell.setCellStyle(cellHeadStyle);
                cell.setCellValue(titleNames[i]);
                sheet.setColumnWidth(i, 7000);
            }
            for (int rowIndex = 0; rowIndex < dataList.size(); rowIndex++) {
                List<String> dataPros = (List) dataList.get(rowIndex);
                Row dataRow = sheet.createRow(rowIndex + 1);
                for (int colIndex = 0; colIndex < dataPros.size(); colIndex++) {
                    Cell cell = dataRow.createCell(colIndex);
                    cell.setCellStyle(dataStyle);
                    cell.setCellValue(dataPros.get(colIndex));
                }
            }
            wb.write(fos);
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequestException(null, "exportToExcel", "导出数据失败");
        } finally {
            try {
                if (Objects.isNull(fos)) {
                    fos.flush();
                    fos.close();
                }
                if (Objects.isNull(wb)) {
                    wb.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //手动清除list
            dataList.clear();
        }
    }

    public static void exportToTxtForRecord(List<?> dataList, String filePath) throws BadRequestException {
        if (Objects.isNull(dataList) || dataList.isEmpty()) {
            throw new BadRequestException(null, "exportToExcel", "无相应数据供导出");
        }
        Writer fw = null;
        try {
            fw = new BufferedWriter(
                    new OutputStreamWriter(
                            new FileOutputStream(filePath), "UTF-8"));
            for (int rowIndex = 0; rowIndex < dataList.size(); rowIndex++) {
                List<String> dataPros = (List) dataList.get(rowIndex);
                for (int colIndex = 0; colIndex < dataPros.size(); colIndex++) {
                    if (ZWStringUtils.isNotEmpty(dataPros.get(colIndex))) {
                        fw.write(dataPros.get(colIndex));
                    } else {
                        fw.write("NA");
                    }
                    if (colIndex != dataPros.size() - 1) {
                        fw.write("|");
                    } else {
                        fw.write("\r\n");
                    }
                }
            }
            fw.flush();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequestException(null, "exportToExcel", "导出数据失败");
        } finally {
            try {
                if (Objects.isNull(fw)) {
                    fw.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //手动清除list
            dataList.clear();
        }
    }

    /**
     * @param titleMap    标题项
     * @param dataMapList 属性值
     * @param filePath    文件路径+文件名称
     */
    public static void exportToExcel(Map<Integer, String> titleMap, List<Map<Integer, String>> dataMapList, String filePath) throws BadRequestException {
        if (Objects.isNull(dataMapList) || dataMapList.isEmpty()) {
            throw new BadRequestException(null, "exportToExcel", "无相应数据供导出");
        }
        FileOutputStream fos = null;
        SXSSFWorkbook wb = null;
        try {
            fos = new FileOutputStream(filePath);
            wb = new SXSSFWorkbook(ROW_MEMORY);
            CellStyle cellHeadStyle = headCellType(wb);
            CellStyle dataStyle = dataCellType(wb);
            //写入头信息
            Sheet sheet = null;
            sheet = wb.createSheet("sheet");
            Row row = sheet.createRow(0);
            Sheet finalSheet = sheet;
            titleMap.forEach((key, value) -> {
                Cell cell = row.createCell(key);
                cell.setCellStyle(cellHeadStyle);
                cell.setCellValue(value);
                finalSheet.setColumnWidth(key, 7000);
            });
            //写入数据
            dataMapList.forEach(map -> {
                int rowIndex = dataMapList.indexOf(map);
                Row dataRow = finalSheet.createRow(rowIndex + 1);
                map.forEach((key, value) -> {
                    Cell cell = dataRow.createCell(key);
                    cell.setCellStyle(dataStyle);
                    cell.setCellValue(value);
                });
            });
            wb.write(fos);
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BadRequestException(null, "exportToExcel", "导出数据失败");
        } finally {
            try {
                if (Objects.isNull(fos)) {
                    fos.flush();
                    fos.close();
                }
                if (Objects.isNull(wb)) {
                    wb.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //手动清除list
            dataMapList.clear();
        }
    }

    public static boolean deleteDir(String path){
        File file = new File(path);
        if(!file.exists()){//判断是否待删除目录是否存在
            System.err.println("The dir are not exists!");
            return false;
        }

        String[] content = file.list();//取得当前目录下所有文件和文件夹
        for(String name : content){
            File temp = new File(path, name);
            if(temp.isDirectory()){//判断是否是目录
                deleteDir(temp.getAbsolutePath());//递归调用，删除目录里的内容
                temp.delete();//删除空目录
            }else{
                if(!temp.delete()){//直接删除文件
                    System.err.println("Failed to delete " + name);
                }
            }
        }
        return true;
    }

    /**
     * 标题
     *
     * @param wb
     * @return
     */
    public static CellStyle headCellType(SXSSFWorkbook wb) {
        CellStyle cellHeadStyle = wb.createCellStyle();
        DataFormat format = wb.createDataFormat();
        cellHeadStyle.setDataFormat(format.getFormat("@"));
        //边框
        cellHeadStyle.setBorderBottom(BorderStyle.THIN);
        cellHeadStyle.setBorderLeft(BorderStyle.THIN);
        cellHeadStyle.setBorderRight(BorderStyle.THIN);
        cellHeadStyle.setBorderTop(BorderStyle.THIN);
        cellHeadStyle.setAlignment(HorizontalAlignment.CENTER);
        //自动换行
        cellHeadStyle.setWrapText(false);
        //字体设置
        Font f = wb.createFont();
        f.setFontHeightInPoints((short) 12);
        f.setBold(true);
        cellHeadStyle.setFont(f);
        return cellHeadStyle;
    }

    /**
     * 数据
     *
     * @param wb
     * @return
     */
    public static CellStyle dataCellType(SXSSFWorkbook wb) {
        CellStyle dataCellType = wb.createCellStyle();
        DataFormat format = wb.createDataFormat();
        dataCellType.setDataFormat(format.getFormat("@"));
        //边框
        dataCellType.setBorderBottom(BorderStyle.THIN);
        dataCellType.setBorderLeft(BorderStyle.THIN);
        dataCellType.setBorderRight(BorderStyle.THIN);
        dataCellType.setBorderTop(BorderStyle.THIN);
        dataCellType.setAlignment(HorizontalAlignment.CENTER);
        //自动换行
        dataCellType.setWrapText(true);
        //字体设置
        Font f = wb.createFont();
        f.setFontHeightInPoints((short) 9);
        f.setBold(false);
        dataCellType.setFont(f);
        return dataCellType;
    }


    public static List<CaseInfoPropertyResponse> getObjejctProperty(List<Class<?>> objClassList){
        List<CaseInfoPropertyResponse> caseInfoPropertyResponseList=new ArrayList<>();
        for(Class<?> objClass : objClassList){
            //获取类中所有的字段
            Field[] fields = objClass.getDeclaredFields();
            for (Field field : fields) {
                //获取标记了ExcelAnno的注解字段
                if (field.isAnnotationPresent(ExcelAnno.class)) {
                    ExcelAnno f = field.getAnnotation(ExcelAnno.class);
                    CaseInfoPropertyResponse caseInfoPropertyResponse=new CaseInfoPropertyResponse();
                    caseInfoPropertyResponse.setAttribute(field.getName());
                    caseInfoPropertyResponse.setName(f.cellName());
                    caseInfoPropertyResponse.setPropertyType(f.fieldDataType().name());
                    caseInfoPropertyResponseList.add(caseInfoPropertyResponse);
                }
            }
        }
        return caseInfoPropertyResponseList;
    }

    /**
     * 文件写入硬盘
     *
     * @param inputStream
     * @param extensionName
     * @param fileId
     * @throws IOException
     */
    public static void saveToDisk(InputStream inputStream, String extensionName, String fileId, String fileDir) throws Exception {
        File outFile = null;
        OutputStream ot = null;
        try {
            outFile = new File(fileDir);
            if (!outFile.exists()) {
                outFile.mkdirs();
            }
            String fileName = extensionName;
            ot = new FileOutputStream(fileDir + "/" + fileName);
            byte[] buffer = new byte[1024];
            int len;
            while ((-1 != (len = inputStream.read(buffer)))) {
                ot.write(buffer, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("file.saveToDisk.error");
        } finally {
            if (Objects.nonNull(ot)) {
                ot.close();
            }
        }
    }
}
